#pragma once

#include <iostream>
#include <memory>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <functional>

#include "Socket.hpp"
#include "Log.hpp"
namespace TcpServerModule
{
    using namespace SocketMudule;
    using namespace LogMudule;

    using tcphandler_t = std::function<bool(SockPtr, InetAddr)>;

    // 是它负责进行IO
    class TcpServer
    {
    public:
        TcpServer(int port)
            : _listenSocket(std::make_unique<TcpSocket>())
            , _running(false)
            , _port(port)
        {
        }

        void InitServer(tcphandler_t handler)
        {
            _handler = handler;
            _listenSocket->BuildTcpSocketMethod(_port);
        }

        void Loop()
        {
            _running = true;
            while (_running)
            {
                // 1.Accept
                InetAddr clientaddr;
                auto sockfd = _listenSocket->Accepter(&clientaddr);
                if (sockfd == nullptr)
                    continue;
                // 2.IO处理
                LOG(LogLevel::INFO) << "Accept a client from " << clientaddr.Addr();

                pid_t id = fork();
                if (id == 0)
                {
                    _listenSocket->Close();
                    if(fork() > 0) {exit(0);}

                    _handler(sockfd, clientaddr);
                    exit(0);
                }
                sockfd->Close();
                ::waitpid(id, nullptr, 0);
            }
            _running = false;
        }


        ~TcpServer()
        {
            _listenSocket->Close();
        }

    private:
        // 一定要有一个Listensocket
        std::unique_ptr<Socket> _listenSocket;
        bool _running;
        tcphandler_t _handler;
        int _port;
    };
}
